package Java进阶.JDK8新特性;

import java.util.Objects;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Predicate;

//jdk8的新特性
public class LambadaTest {

	//接口1
	static interface Inf1 {
		String say(String name , String word);
	}
	
	//接口2
	static interface Inf2 {
		String say(String name);
	}
	

	//接口2
	static interface Inf3 {
		void say();
	}
	
	public static void main(String[] args) {
		
		//普通方式
		Inf1 inf1 = new Inf1() {
			@Override
			public String say(String name , String word) {
				return name + " say : " + word;
			}
		};
		
		//lambada形式
		Inf1 inf1_1= (String name , String word) -> {
			System.out.println("===========");
			return name + " say : " + word;
		};
		
		/**
		 * lambada简写形式
		 * 1.形参数据列表中的数据类型可以不写,会自动推断
		 * 2.如果方法体体中只有一句,则可以省略花括号,如果是renturn返回数据的,可以省略到return
		 */
		Inf1 inf1_2= (name , word) ->  name + " say : " + word;
		
		//若只有一个参数的,可以省略括号()
		Inf2 inf2 = name -> name + " say : ";
		
		//无参和无返回值的写法
		Inf3 inf3 = () -> System.out.print("abc"); 
		
		//无参也无方法体的写法
		Inf3 inf3_1 = () -> {}; 
		
		//lambada表达式内部的变量会认为是final类型
		String myWord = "abc";
		Inf2 inf2_1 = name -> name + " say : " + myWord;
		
		//这里赋值,上面的语句会报错,因为上面认为myWord是个final类型
		//myWord = "xy";
		
		/**
		 * lambada构造方法引用
		 */
		PersonFactory pf = new PersonFactory() {
			public Person createPerson(String name, String sex) {
				return new Person(name, sex);
			}
		};
		
		//lambada写法
		PersonFactory pf_1 = (name , sex) -> {return new Person(name, sex);};
		
		//更为简洁的写法,称之为构造方法引用,要求参数列表和构造方法的参数是一致的,类型和数量要一致
		PersonFactory pf_2 = Person::new;
		
		pf_2.createPerson("张飞", "男");
		
		/**
		 * 静态方法引用,实现方式为引用别的类的静态方法
		 */
		ParseInterface pif = new ParseInterface() {
			@Override
			public int parse(String a) {
				return Integer.parseInt(a);
			}
		};
		
		//lambada写法
		ParseInterface pif_1 = a -> Integer.parseInt(a);
		
		//更为简洁的写法,称之为静态方法引用 , 那么静态方法的返回值要和要实现的方法的返回值一样
		ParseInterface pif_2 = Integer :: parseInt;
		
		pif_2.parse("123");
		
		//静态方法的返回值要和要实现的方法的返回值一样
		Predicate<String> p = s -> s == null;    //要实现的方法只有test
		p = Objects::isNull;   //判断结构作为test方法的判断结构,把obj == null;引用到了这里,省的写了.
		
		/**
		 * 实例方法引用
		 * 需求 : 想写一个匿名内部类来实现对String类的startWith的封装
		 */
		
		String text = "happy_day";
		
		//普通写法
		StringStartWithInface ssw = new StringStartWithInface() {
			public boolean startWith(String s) {
				return text.startsWith(s);
			}
		};
		
		
		//还有一种函数式匿名内部类的写法
		Function<String, Boolean> f = new Function<String, Boolean>() {
			@Override
			public Boolean apply(String s) {
				return text.startsWith(s);
			}
		};
		
		//lambada写法
		Function<String, Boolean> f1 = s -> text.startsWith(s);
		
		//更为简洁的写法,称之为对象方法引用
		Function<String, Boolean> f2 =text::startsWith;

		//调用方式,用apply
		System.out.println(f2.apply("happy"));
		
		
		//多个参数的function
		
//		 * @param <T> the type of the first argument to the function  第一个参数的类型
//		 * @param <U> the type of the second argument to the function 第二个参数的类型
//		 * @param <R> the type of the result of the function     返回值的类型
		BiFunction<Long , Integer , Long> bif = (s , b) ->s + b;
		
		System.out.println(bif.apply(1L , 2));
	
	}
	
	
	
	
}
